#ifndef _xMappingNode_H_
#define	_xMappingNode_H_
/*------------------------------------------------------------
  2008/5/18 By YPC
   xMappingNode is of the new mapping node design (please see design document)
   There is no more VVnode and WVnode in this new design.
   "x" means X-man mapping node.
   a xMappingNode can accept abitrary kinds of connections 
   (from WOPs, VMs, collectors, or arithmetic operator
  --------------------------------------------------------------
*/

   
#include <vector>
#include "vmLibrary.h"
#include "xNodeType.h"

class xInMappingPort ;
class xOutMappingPort ;
class xMappingNode {

protected:
	friend class xNodeType_VM ;
	friend class xNodeType_WOP ;
	friend class xNodeType_vmcollector ;
	friend class xNodeType_wopcollector ;
	friend class xNodeType_Math ;
	friend class xNodeType_gate ;
	friend class xNodeType_vmclone;
	friend class xNodeType_composite ;
	friend class xNodeType_Clock ;
	friend class xNodeType_StringComposer;
	friend class xNodeType_TM;
	friend class xNodeType_existing;
	xNodeType   *_nodetype ;
	int			_level_id ;
	int			_serial_no ;
	xMappingNode* _composite_parent ;
	static int  xMappingNodeNumber ;

	// linkage to other mapping nodes
	std::vector<xInMappingPort *> _inports ; // an xInMappingPort accepts only one linkage
	std::vector<xOutMappingPort*> _outports ; // an xOutMappingPort accepts more than one linkages to other mapping nodes
	// for example, when a mapping node output a wop_entry or constants
	// it may be linked to arbitrary number of other mapping nodes
	bool _isForeachElements; // true if node is repeat for each array elements
	bool _isUnfold;          // true if xMappingNode is ref type and is unfolded by clicking plus icon
	std::vector<xMappingNode* > _unfoldChildren;
	bool _MDSFlag;
public:
	xMappingNode() ; // get a empty mapping node
	xMappingNode(xNodeType *p) ;

	///** create a mapping node with a vmdescriptor pointer to set up the ports */
	//xMappingNode(vmdescriptor *vd) ;
	///** create a mapping node with VM id to setup all the ports */
	//xMappingNode(int vmid) { xMappingNode(vmLibrary::getInstance()->get_vmdescriptor(vmid)); } 

	~xMappingNode() ;
	
	void setNodeType(xNodeType *nd) { _nodetype = nd ; }
	xNodeType * getNodeTypePtr() { return _nodetype ; }
	std::string getType();

	/** a mapping node may belong to some composite mapping node , this method sets the composite mapping node
	that owns it. */
	void setCompositeParent(xMappingNode *p) { _composite_parent = p ; }

	xMappingNode * getCompositeParent() { return _composite_parent ; }

	std::vector<xOutMappingPort *> getOutports() { return _outports ; }
	int getOutportSize() { return _outports.size(); }
	/** get outport */
	xOutMappingPort* getOutPort(unsigned int i ) { assert(i < _outports.size()) ; return _outports[i];} 
	xOutMappingPort* getOutPort(string name);
	int getOutportIndex(xOutMappingPort *p) ;

	/** get the number of inports */
	int getInportSize() { return _inports.size(); }
	/** get the inport by index i. i begins with 0 to inports.size()-1 */
	std::vector<xInMappingPort *> getInports() { return _inports ; }
	xInMappingPort * getInPort(unsigned int i) const;
	xInMappingPort * getInPort(string pname) const;
	int getInportIndex(xInMappingPort *p) ;

	xInMappingPort * newInPort(std::string name, std::string type, MNClass para_class, std::string defaultvalue, MNCategory category) ;
	xOutMappingPort * newOutPort(std::string name, std::string type, MNClass para_class, std::string defaultvalue,  MNCategory category) ;

	void deletePort(int i) ;
	void deleteUnfoldedChild( xMappingNode * nd );

	/** set the level of this mapping node (often in a mapping tree, the level is meaningful) */
	void set_level(int id) { _level_id = id ; }
	int get_level() { return _level_id ; }

	/** clear all the incoming ports and out port */
	void clear_ports() ;

	/** clean the node type and remove all the inports and outports */
	void clean_nodetype();

	/** clean the old node type and apply a new node type */
	void apply_nodetype(xNodeType * nt); 

	std::string toMDString(xNodeType::MDSType type);

	int getSerialNo() { return _serial_no; }

	std::vector<xMappingNode*>  getParentNodes() ;

	std::vector<xMappingNode*>  getChildNodes() ;

	bool isForeachElements() { return _isForeachElements; }
	void setForeachElements(bool t) { _isForeachElements = t; }

	bool isUnfold() { return _isUnfold; }
	void setUnfold(bool t){ _isUnfold = t;}

	void addUnfoldChild(xMappingNode* child);
	std::vector<xMappingNode*>& getUnfoldChildren();

	void setMDSFlag(bool b);
	bool getMDSFlag();
};
#endif 
